package com.android.openapp.ui;

import java.util.HashMap;

import com.android.openapp.services.Controller;
import com.android.openapp.services.Controller.ControllerBinder;
import com.android.openapp.R;
import com.google.android.maps.MapView;
import com.socrata.util.Variables;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.app.SearchManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TabHost;
import android.widget.TextView;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;

/**
 * Usando le librerie support.v4.googlemaps (hackate) la classe FragmentActivity
 * estende MapActivity. e' quindi possibile usare una MapView all'interno di un Fragment.
 * @author Simone Panza
 * date 2012_08_28
 */
public class MainActivity extends FragmentActivity{

	public static String TAG = "OpenApp";
	
	public static final int FRAGMENT_PLACES = 0;
	public static final int FRAGMENT_MAP = 1;
	public static final int FRAGMENT_SETTINGS = 2;
	
	public static String FRAGMENT_ID_PLACES = "interest_places";
	public static String FRAGMENT_ID_MAP = "map";
	public static String FRAGMENT_ID_SETTINGS = "settings";
	
	public static String VIEW_MAP_TAB = "VIEW MAP TAB";
	public static String VIEW_PLACES_TAB = "VIEW PLACES TAB";
	public static String BOOKMARKS_LIST_UPDATED = "BOOKMARKS LIST UPDATED";
	
	TabHost mTabHost;
	TabManager mTabManager;
	
	ControllerBinder mBinder;
	ProgressDialog pd;
	ConnectivityManager mConnManager;
	LocationManager mLocationM;
	
	public static float screenDensity;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        createTabView();
        
        //check GPS
        mLocationM = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        mConnManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        
        //binding al Controller (service)
        Intent i = new Intent(this, Controller.class);
        bindService(i, conn, Context.BIND_AUTO_CREATE);
        
        initializeMapView();
        
        handleIntent(getIntent()); //per gestire la ricezione di un Intent di tipo ACTION_SEARCH
        
		//check GPS
		if (mLocationM.getProvider(LocationManager.GPS_PROVIDER) == null) 
        	Utils.showToast(this, R.string.GPS_unavailable);
        if (!mLocationM.isProviderEnabled(LocationManager.GPS_PROVIDER)) 
        	Utils.showToast(this, R.string.GPS_off);
        
        screenDensity = getResources().getDisplayMetrics().density;
    }
    
    /**
     * Quando viene effettuata una ricerca, viene mandato
     * un Intent alla MainActivity
     */
    @Override
    public void onNewIntent(Intent intent) {
    	setIntent(intent);
    	handleIntent(intent);
    }
    
    /**
     * Gestione degli Intent di ricerca
     * @param intent
     */
    private void handleIntent(Intent intent){
    	if (intent.getAction().equals(Intent.ACTION_SEARCH)) {
			//passo sempre al tab della lista
    		mTabHost.setCurrentTab(FRAGMENT_PLACES);
    		
    		String query = intent.getStringExtra(SearchManager.QUERY);
			Log.v(TAG, "search intent received: "+query);
			
			mBinder.searchForPlaces(query);
			//ci pensera' poi il SearchData ad inviare un intent per segnalare che la ricerca e' finita
		}
    }
    
    protected void createTabView(){
    	// set up tabs
        mTabHost = (TabHost) findViewById(android.R.id.tabhost);
        mTabHost.setup();
        
        mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
        
        Resources res = getResources();
        
        //add tabs
        mTabManager.addTab(mTabHost.newTabSpec(FRAGMENT_ID_PLACES).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_myplaces)),
        		PlacesListFragment.class, null);
        mTabManager.addTab(mTabHost.newTabSpec(FRAGMENT_ID_MAP).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_mapmode)),
        		MapFragment.class,null);
        mTabManager.addTab(mTabHost.newTabSpec(FRAGMENT_ID_SETTINGS).
        		setIndicator("", res.getDrawable(R.drawable.ic_menu_preferences)),
        		SettingsFragment.class,null);
    }
    
    protected void onDestroy() {
    	super.onDestroy();
    	unbindService(conn);
    }
    
    @Override
    protected void onStart() {
    	super.onStart();
    	//register receivers
    	IntentFilter filter;
		filter = new IntentFilter(Variables.DOWNLOAD_FINISHED);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(VIEW_MAP_TAB);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(VIEW_PLACES_TAB);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(Variables.DOWNLOAD_METADATA_FINISHED);
		registerReceiver(mServiceReceiver, filter);
		filter = new IntentFilter(BOOKMARKS_LIST_UPDATED);
		registerReceiver(mServiceReceiver, filter);
		
    }
    
    @Override
    protected void onStop() {
    	super.onStop();
    	unregisterReceiver(mServiceReceiver);
    }
    
    private void showTutorial(){
    	Resources res = getResources();
		String[] tutorialStrings = res.getStringArray(R.array.tutorial_strings);
		
		TutorialDialog td = new TutorialDialog(this, R.layout.tutorial, R.id.mtextswitcher);
		td.setTextStrings(tutorialStrings);
		td.setTitle(R.string.tutorial);
		td.showWithIcon();
	}
    
    public void onBackPressed() {
    
    	 AlertDialog.Builder builder = new AlertDialog.Builder(this);
         builder.setMessage(R.string.exit_message)
                .setCancelable(false)
                .setPositiveButton("Si", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                    	finish();
              
                    }
                })
                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                         dialog.cancel();
                    }
                });
         AlertDialog alert = builder.create();
         alert.show();
         
         
    };
    
    
    /**
     * Oggetto di tipo ServiceConnection che gestisce il binding/unbinding al servizio Controller
     */
    ServiceConnection conn = new ServiceConnection() {
		
		@Override
		public void onServiceDisconnected(ComponentName name) {
			
		}
		
		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			mBinder = (ControllerBinder) service;
			mBinder.setActivity(MainActivity.this);
			mBinder.setBookmarks();//load bookmarks
			//avverto i fragment che ho fatto il binding
			mCurrentFragment.onBind(mBinder);
		}
	};
	
	/**
	 * Gestione dei messaggi (Intent) in arrivo dal Service
	 */
	BroadcastReceiver mServiceReceiver = new BroadcastReceiver() {
		
		@Override
		public void onReceive(Context context, Intent intent) {
			String action = intent.getAction();
			Log.v(TAG,action);
			if (action.equals(Variables.DOWNLOAD_FINISHED)) {
				switch(intent.getExtras().getInt(Variables.DOWNLOAD_RESULT)){
				case Variables.NO_ERROR:
					Log.d("DOWNLOAD FINISHED", "DOWNLOAD SUCCESFULLY COMPLETED!");
					mCurrentFragment.onDataReceived();
					break;
				case Variables.DOWNLOAD_ERROR:
					Log.d("DOWNLOAD FINISHED", "DOWNLOAD ERROR!");
					//TODO anche in caso di errore chiamo mCurrentFragment.onDataReceived(); ?
					break;
				}
			}
			else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)){
				
		        NetworkInfo activeNetwork = mConnManager.getActiveNetworkInfo();
		        boolean connecting = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
		        
				if(!connecting && intent.getExtras().getBoolean(ConnectivityManager.EXTRA_NO_CONNECTIVITY)){
					String title = getResources().getString(R.string.network_off_title);
					// costruisco il Dialog
					AlertDialog.Builder builder = new AlertDialog.Builder(context);
					builder.setIcon(android.R.drawable.ic_dialog_info).setMessage(R.string.network_off).
					setTitle(title).setCancelable(false)
						.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
							
							@Override
							public void onClick(DialogInterface dialog, int which) {
								//do nothing
							}
						})
						.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
								public void onClick(DialogInterface dialog, int id) {
									Intent i = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
									//i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
									startActivity(i);
								}
							});
					
					AlertDialog dialog = builder.create();
					dialog.show();
					
					
					//Utils.showToast(context, R.string.network_off);
				}
			}
			else if (action.equals(VIEW_MAP_TAB)){
				mTabHost.setCurrentTab(FRAGMENT_MAP);
				int index = intent.getExtras().getInt("index");
				mCurrentFragment.onLocationReceived(index);
			}
			else if (action.equals(VIEW_PLACES_TAB)){
				mTabHost.setCurrentTab(FRAGMENT_PLACES);
			}
			else if (action.equals(BOOKMARKS_LIST_UPDATED)){
				mCurrentFragment.onBookmarksListUpdated();
			}
			else if (action.equals(Variables.DOWNLOAD_METADATA_FINISHED)){
				if(intent.getExtras().getInt(Variables.DOWNLOAD_RESULT) == Variables.NO_ERROR){
					// se e' la prima installazione, mostra il tutorial
					boolean firstrun = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("firstrun", true);
					if (firstrun){
						mTabHost.setCurrentTab(FRAGMENT_SETTINGS);
						showTutorial();
						
						getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putBoolean("firstrun", false).commit();
					}
				}
			}
			
		}
	};
		
	FragmentInteract mCurrentFragment;
	public void setCurrentFragment(FragmentInteract fragment){
		mCurrentFragment = fragment;
	}
    
	/**
	 * menu About
	 */
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_main, menu);
        return true;
    }
    
    @Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		// We have only one menu option
		case R.id.menu_about:
			// preparo la view da visualizzare nel Dialog
	        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
	        View layout = inflater.inflate(R.layout.about, null);
	        String title = getString(R.string.about_title);
	        
	        // costruisco il Dialog
			AlertDialog.Builder builder = new AlertDialog.Builder(this);
			builder.setView(layout).setIcon(android.R.drawable.ic_dialog_info).
			setTitle(title).setCancelable(true)
				.setPositiveButton("OK", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
						}
					});
			AlertDialog dialog = builder.create();
			dialog.show();
			
			//version name
	        try {
				String appVer = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
				TextView version = (TextView) dialog.findViewById(R.id.about2);
		        version.setText("version " + appVer);
			} catch (NameNotFoundException e) {
				e.printStackTrace();
			}
			
			break;
		}
		return true;
	}
    
    /*
     * Methods for MapActivity
     * Using the hacked support library v4: FragmentActivity extends MapActivity
     * so we can show a MapView into a Fragment.
     */
    
    @Override
    protected boolean isRouteDisplayed() {
    	return false;
    }
    
	View mMapViewContainer;
	MapView mMapView;
    
    private void initializeMapView(){
    	mMapViewContainer = LayoutInflater.from(this).inflate(R.layout.maplayout, null);
    	mMapView = (MapView) mMapViewContainer.findViewById(R.id.mapview);
    }
    
    /**
     * This is a helper class that implements a generic mechanism for
     * associating fragments with the tabs in a tab host.  It relies on a
     * trick.  Normally a tab host has a simple API for supplying a View or
     * Intent that each tab will show.  This is not sufficient for switching
     * between fragments.  So instead we make the content part of the tab host
     * 0dp high (it is not shown) and the TabManager supplies its own dummy
     * view to show as the tab content.  It listens to changes in tabs, and takes
     * care of switch to the correct fragment shown in a separate content area
     * whenever the selected tab changes.
     */
    public static class TabManager implements TabHost.OnTabChangeListener {
        private final FragmentActivity mActivity;
        private final TabHost mTabHost;
        private final int mContainerId;
        private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
        TabInfo mLastTab;

        static final class TabInfo {
            private final String tag;
            private final Class<?> clss;
            private final Bundle args;
            private Fragment fragment;

            TabInfo(String _tag, Class<?> _class, Bundle _args) {
                tag = _tag;
                clss = _class;
                args = _args;
            }
        }

        static class DummyTabFactory implements TabHost.TabContentFactory {
            private final Context mContext;

            public DummyTabFactory(Context context) {
                mContext = context;
            }

            @Override
            public View createTabContent(String tag) {
                View v = new View(mContext);
                v.setMinimumWidth(0);
                v.setMinimumHeight(0);
                return v;
            }
        }

        public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
            mActivity = activity;
            mTabHost = tabHost;
            mContainerId = containerId;
            mTabHost.setOnTabChangedListener(this);
        }

        public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
            tabSpec.setContent(new DummyTabFactory(mActivity));
            String tag = tabSpec.getTag();

            TabInfo info = new TabInfo(tag, clss, args);

            // Check to see if we already have a fragment for this tab, probably
            // from a previously saved state.  If so, deactivate it, because our
            // initial state is that a tab isn't shown.
            info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
            if (info.fragment != null && !info.fragment.isDetached()) {
                FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
                ft.detach(info.fragment);
                ft.commit();
            }

            mTabs.put(tag, info);
            mTabHost.addTab(tabSpec);
        }

        @Override
        public void onTabChanged(String tabId) {
            TabInfo newTab = mTabs.get(tabId);
            if (mLastTab != newTab) {
                FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
                if (mLastTab != null) {
                    if (mLastTab.fragment != null) {
                        ft.detach(mLastTab.fragment);
                    }
                }
                if (newTab != null) {
                    if (newTab.fragment == null) {
                        newTab.fragment = Fragment.instantiate(mActivity,
                                newTab.clss.getName(), newTab.args);
                        ft.add(mContainerId, newTab.fragment, newTab.tag);
                    } else {
                        ft.attach(newTab.fragment);
                    }
                }

                mLastTab = newTab;
                ft.commit();
                mActivity.getSupportFragmentManager().executePendingTransactions();
            }
        }
    }
}